package com.wimcorp.magic.dataloader.abilities;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONParser;
import com.google.gwt.json.client.JSONString;
import com.google.gwt.json.client.JSONValue;
import com.google.gwt.user.client.ui.CellPanel;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.wimcorp.magic.data.AbilityData;
import com.wimcorp.magic.data.CostData;
import com.wimcorp.magic.input.AbilityInput;
import com.wimcorp.magic.input.AbilityTriggerInput;

public class ConditionAbilityWidget extends AbilityWidget {

	private ListBox conditionList;
	private VerticalPanel nonConditionVP;
	private VerticalPanel conditionVP;
	private AbilityWidget nonConditionAbilityWidget;
	private AbilityWidget conditionAbilityWidget;

	public ConditionAbilityWidget(AbilityInput ability) {
		super(ability);
		setName(ability.toString());
	}

	protected void initAbilityFields() {
		conditionList = new ListBox();

		HorizontalPanel nonConditionAbilityPanel = new HorizontalPanel();
		nonConditionAbilityPanel.add(new Label("Non-Condition"));
		nonConditionVP = new VerticalPanel();
		nonConditionAbilityPanel.add(nonConditionVP);
		initNonConditionAbilityPanel();
		getConfigurationPanel().add(nonConditionAbilityPanel);

		HorizontalPanel conditionAbilityPanel = new HorizontalPanel();
		conditionAbilityPanel.add(new Label("Condition"));
		conditionVP = new VerticalPanel();
		conditionAbilityPanel.add(conditionVP);
		initConditionAbilityPanel();
		getConfigurationPanel().add(conditionAbilityPanel);
		addInputSingleConditionOption(conditionList);
	}

	private void initNonConditionAbilityPanel() {
		nonConditionVP.add(new Label("Abilities"));
		nonConditionVP.setStyleName("abilityPanel");
		for (AbilityInput ability : AbilityInput.values()) {
			final VerticalPanel panel = new VerticalPanel();
			final CheckBox abilityCheckBox = createCheckBox(ability.toString(), ability.getName());
			panel.add(abilityCheckBox);
			abilityCheckBox.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
				@Override
				public void onValueChange(ValueChangeEvent<Boolean> event) {
					if (abilityCheckBox.getValue()) {
						nonConditionAbilityWidget = AbilityWidget.createAbilityWidget(AbilityInput
								.valueOf(abilityCheckBox.getName()));
						panel.add(nonConditionAbilityWidget.getConfigurationPanel());
					} else {
						nonConditionAbilityWidget = null;
						Widget w = panel.getWidget(0);
						panel.clear();
						panel.add(w);
					}
				}
			});
			nonConditionVP.add(panel);
		}
	}

	private void initConditionAbilityPanel() {
		conditionVP.add(new Label("Abilities"));
		conditionVP.setStyleName("abilityPanel");
		for (AbilityInput ability : AbilityInput.values()) {
			final VerticalPanel panel = new VerticalPanel();
			final CheckBox abilityCheckBox = createCheckBox(ability.toString(), ability.getName());
			panel.add(abilityCheckBox);
			abilityCheckBox.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
				@Override
				public void onValueChange(ValueChangeEvent<Boolean> event) {
					if (abilityCheckBox.getValue()) {
						conditionAbilityWidget = AbilityWidget.createAbilityWidget(AbilityInput.valueOf(abilityCheckBox
								.getName()));
						panel.add(conditionAbilityWidget.getConfigurationPanel());
					} else {
						conditionAbilityWidget = null;
						Widget w = panel.getWidget(0);
						panel.clear();
						panel.add(w);
					}
				}
			});
			conditionVP.add(panel);
		}
	}

	public JSONObject getAbilityConfig() {
		JSONObject config = new JSONObject();

		if (nonConditionAbilityWidget != null) {
			JSONObject nonConditionAbility = new JSONObject();
			nonConditionAbility.put("name", new JSONString(nonConditionAbilityWidget.getName()));
			nonConditionAbility.put("config", nonConditionAbilityWidget.getAbilityConfig());
			config.put("nonConditionAbility", nonConditionAbility);
			JSONArray nonConditionAbilityCosts = getCostconfig(nonConditionAbilityWidget.getCosts());
			config.put("nonConditionAbilityCosts", nonConditionAbilityCosts);
		}
		JSONObject conditionAbility = new JSONObject();
		conditionAbility.put("name", new JSONString(conditionAbilityWidget.getName()));
		conditionAbility.put("config", conditionAbilityWidget.getAbilityConfig());
		config.put("conditionAbility", conditionAbility);

		JSONArray conditionAbilityCosts = getCostconfig(conditionAbilityWidget.getCosts());
		config.put("conditionAbilityCosts", conditionAbilityCosts);
		config.put("condition", getSelectedItems(conditionList));
		config.put("trigger", new JSONString(AbilityTriggerInput.CONDITION_TRIGGER.toString()));
		return config;
	}

	private JSONArray getCostconfig(Set<CostData> costs) {
		JSONArray abilityCosts = new JSONArray();
		int i = 0;
		for (CostData cost : costs) {
			JSONObject conditionAbilityCost = new JSONObject();
			conditionAbilityCost.put("cost", new JSONString(cost.getCost()));
			conditionAbilityCost.put("config", (JSONObject) JSONParser.parseLenient(cost.getConfig()));
			abilityCosts.set(i, conditionAbilityCost);
			i++;
		}
		return abilityCosts;
	}

	public void load(AbilityData abilityData) {
		try {
			JSONObject config = (JSONObject) JSONParser.parseLenient(abilityData.getConfig());
			loadListBox(conditionList, config.get("condition"));

			JSONObject nonConditionAbility = (JSONObject) config.get("nonConditionAbility");
			if (nonConditionAbility != null) {
				JSONValue name = nonConditionAbility.get("name");
				JSONValue abilityConfig = nonConditionAbility.get("config");
				AbilityInput abilityInput = AbilityInput.valueOf(toString(name));
				nonConditionAbilityWidget = AbilityWidget.createAbilityWidget(abilityInput);
				Set<CostData> costs = loadCosts((JSONArray) config.get("nonConditionAbilityCosts"));
				nonConditionAbilityWidget
						.load(new AbilityData(abilityInput.toString(), abilityConfig.toString(), costs));
				loadAbilityPanel(nonConditionVP, nonConditionAbilityWidget);
			}
			JSONObject conditionAbility = (JSONObject) config.get("conditionAbility");
			if (conditionAbility != null) {
				JSONValue name = conditionAbility.get("name");
				JSONValue abilityConfig = conditionAbility.get("config");
				AbilityInput abilityInput = AbilityInput.valueOf(toString(name));
				conditionAbilityWidget = AbilityWidget.createAbilityWidget(abilityInput);

				Set<CostData> costs = loadCosts((JSONArray) config.get("conditionAbilityCosts"));
				conditionAbilityWidget.load(new AbilityData(abilityInput.toString(), abilityConfig.toString(), costs));
				loadAbilityPanel(conditionVP, conditionAbilityWidget);
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private Set<CostData> loadCosts(JSONArray abilityCosts) {
		Set<CostData> costs = new HashSet<>();
		if (abilityCosts != null) {
			for (int i = 0; i < abilityCosts.size(); i++) {
				JSONObject conditionAbilityCost = (JSONObject) abilityCosts.get(i);
				costs.add(new CostData(toString(conditionAbilityCost.get("cost")), toString(conditionAbilityCost
						.get("config"))));

			}
		}
		return costs;
	}

	private void loadAbilityPanel(final CellPanel abilityPanel, final AbilityWidget checkedAbilityWidget) {
		Iterator<Widget> panelIterator = abilityPanel.iterator();
		while (panelIterator.hasNext()) {
			Widget panel = panelIterator.next();
			if (panel instanceof CellPanel) {
				CellPanel checkBoxPanel = (CellPanel) panel;
				Iterator<Widget> checkBoxIterator = checkBoxPanel.iterator();
				while (checkBoxIterator.hasNext()) {
					Widget c = checkBoxIterator.next();
					if (c instanceof CheckBox) {
						CheckBox checkbox = (CheckBox) c;
						checkbox.getName();
						if (checkbox.getName().equals(checkedAbilityWidget.getName())) {
							checkbox.setValue(true);
							checkBoxPanel.add(checkedAbilityWidget.getConfigurationPanel());
						}
					}
				}
			}
		}
	}
}
